﻿using SelfHosting.Handlers.Compression;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SelfHosting.Handlers
{
    /// <summary>
    /// Gestion de la compression
    /// </summary>
    public class CompressionHandler : DelegatingHandler
    {
        /// <summary>
        /// Obtient ou définit la collection des compresseurs
        /// </summary>
        public Collection<ICompressor> Compressors { get; private set; }

        /// <summary>
        /// Constructeur de la classe CompressionHandler
        /// </summary>
        public CompressionHandler()
        {
            Compressors = new Collection<ICompressor>();
            Compressors.Add(new GZipCompressor());
            Compressors.Add(new DeflateCompressor());
        }

        /// <summary>
        /// Envoi d'une requête HTTP compressé
        /// </summary>
        /// <param name="request">requête</param>
        /// <param name="cancellationToken">objet permettant d'annuler l'opération</param>
        /// <returns>objet représentant l'opération asynchrone</returns>
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>((responseToCompleteTask) =>
                {
                    HttpResponseMessage response = responseToCompleteTask.Result;
                    if (response.Content != null && request.Headers.AcceptEncoding != null)
                    {
                        var encoding = request.Headers.AcceptEncoding.FirstOrDefault();
                        if (encoding != null)
                        {
                            var compressor = Compressors.FirstOrDefault(c => c.EncodingType.Equals(encoding.Value, StringComparison.InvariantCultureIgnoreCase));
                            if (compressor != null)
                            {
                                response.Content = new CompressedContent(response.Content, compressor);
                            }
                        }
                    }
                    return response;
                }, TaskContinuationOptions.OnlyOnRanToCompletion);
        }
    }
}
